using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Linq;

namespace Common
{
    /// <summary>
    /// 一些类型转换的函数。Int IsMy_yxh
    /// </summary>
    public static partial class ValueProc
    {
        public static int IndexOf<TSource>(this IEnumerable<TSource> Source, TSource one)
        {
            return IndexOf(Source, one, (a, b) => { return a.Equals(b); });
        }

        public static int IndexOf<TSource>(this IEnumerable<TSource> Source, TSource one, Func<TSource, TSource, bool> func)
        {
            int retVal = -1;
            using (IEnumerator<TSource> e1 = Source.GetEnumerator())
            {
                while (e1.MoveNext())
                {
                    retVal++;
                    if (func(one, e1.Current))
                        return retVal;
                }

            }
            return retVal;
        }

        public static IEnumerable<string> Split(this string Source, string splitString)
        {
            int currPos = 0;
            int nextPos = 0;

            while (true)
            {
                nextPos = Source.IndexOf(splitString, currPos);
                if (nextPos < 0)
                {
                    yield return Source.Substring(currPos, Source.Length - currPos);
                    yield break;
                }
                else
                {
                    yield return Source.Substring(currPos, nextPos - currPos);
                }

                currPos = nextPos + splitString.Length;
                if (currPos >= Source.Length) yield break;
            }

        }

        public static IEnumerable<TSource> InsertAlternate<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
        {
            using (IEnumerator<TSource> e1 = first.GetEnumerator())
            using (IEnumerator<TSource> e2 = second.GetEnumerator())
            {
                while (e1.MoveNext())
                {
                    yield return e1.Current;

                    if (e2.MoveNext())
                    {
                        yield return e2.Current;
                    }
                }

                while (e2.MoveNext())
                {
                    yield return e2.Current;
                }
            }
        }

        /// <summary>
        /// 返回相同个数的两个部分的交替组合.
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> IntersectAndAlternate<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
        {
            using (IEnumerator<TSource> e1 = first.GetEnumerator())
            using (IEnumerator<TSource> e2 = second.GetEnumerator())
                while (e1.MoveNext() && e2.MoveNext())
                {
                    yield return e1.Current;
                    yield return e2.Current;
                }
        }

        public static IEnumerable<T> ToMyList<T>(this IEnumerable source, Func<object, T> func)
        {
            IEnumerable<T> val = source as IEnumerable<T>;
            if (val != null)
            {
                return val;
            }
            else return __ToMyList(source, func);
        }
        private static IEnumerable<T> __ToMyList<T>(this IEnumerable source, Func<object, T> func)
        {
            var e = source.GetEnumerator();
            while (e.MoveNext())
            {
                yield return func(e.Current);
            }
        }

        /// <summary>
        /// 把 Byte 数据序列化为两位一个 Byte 的整齐的十六进制表示形式。和 GetBytesFromHexString 对应使用。 IsMy_yxh
        /// </summary>
        /// <param name="ListBytes"></param>
        /// <returns></returns>
        public static string ToHexString(byte[] ListBytes)
        {
            string strRet = "";
            foreach (byte byt in ListBytes)
            {
                strRet += string.Format("{0:X2}", byt);
            }
            return strRet;
        }

        /// <summary>
        /// 把两位一个 Byte 的整齐的十六进制表示形式 转换为 Byte 数组。和 ToHexString 对应使用。 IsMy_yxh
        /// </summary>
        /// <param name="strBytes"></param>
        /// <returns></returns>
        public static List<byte> GetBytesFromHexString(string strBytes)
        {
            List<byte> li_Bytes = new List<byte>();
            for (int i = 0; i < strBytes.Length; i = i + 2)
            {
                byte byt = 0;
                byt = Convert.ToByte(Uri.FromHex(strBytes[i]) * 16 + Uri.FromHex(strBytes[i + 1]));
                li_Bytes.Add(byt);
            }
            return li_Bytes;
        }

        /// <summary>
        /// 暗文（不显示字符）的 列分隔符。
        /// </summary>
        public const char SplitCell = (char)7;
        /// <summary>
        /// 暗文（不显示字符）的 行分隔符。
        /// </summary>
        public const char SplitLine = (char)8;
        /// <summary>
        /// 暗文（不显示字符）的 段分隔符。
        /// </summary>
        public const char SplitSect = (char)9;

        /// <summary>
        /// 明文的数组分隔符  ,
        /// </summary>
        public const char Comma = ',';

        /// <summary>
        /// 明文模板的字界符 %
        /// </summary>
        public const char Percent = '%';

        /// <summary>
        /// 转换并装箱。
        /// </summary>
        /// <param name="type"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static T Get<T>(object Value)
        {
            return (T)Get(typeof(T), Value);
        }


        /// <summary>
        /// 给数组添加一个值。
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="data"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static IEnumerable<TSource> AddOne<TSource>(this IEnumerable<TSource> data, TSource Value)
        {
            if (data == null) return new TSource[1] { Value };
            return data.Concat(new TSource[1] { Value });
        }

        public static IEnumerable<TSource> Minus<TSource>(this IEnumerable<TSource> data, IEnumerable<TSource> other)
        {
            if (other != null)
            {
                return data.Where(o => (o.IsIn(other.ToArray()) == false));
            }
            else return data;
        }

        public static TSource[] GetSub<TSource>(this IEnumerable<TSource> source, int startIndex, int endIndex)
        {
            List<TSource> retVal = new List<TSource>();
            for (int i = startIndex; i < endIndex; i++)
            {
                retVal.Add(source.ElementAt(i));
            }
            return retVal.ToArray();
        }

        public static bool IsIn<T>(this T one, params T[] Source)
        {
            return Source.Contains(one);
        }

        public static bool IsIn<T>(this T one, IEqualityComparer<T> func, params T[] Source)
        {
            return Source.Contains(one, func);
        }

        public static bool IsIn<T>(this T one, IEnumerable<T> Source)
        {
            return Source.Contains(one);
        }

        /// <summary>
        /// 从字符串里，取出第一个数值内容。
        /// </summary>
        /// <param name="Value"></param>
        /// <param name="DefaultValue"></param>
        /// <returns></returns>
        public static int TakeOutInt(this string Value)
        {
            return TakeOutInt(Value, 0);
        }

        /// <summary>
        /// 从字符串里，取出第一个数值内容。
        /// </summary>
        /// <param name="Value"></param>
        /// <param name="DefaultValue"></param>
        /// <returns></returns>
        public static int TakeOutInt(this string Value, int DefaultValue)
        {
            if (Value.HasValue() == false) return DefaultValue;

            //匹配不是URL转义的带有％3 这种形式的数字。 @"(?<!%)\d+"

            Regex rex = new Regex(@"[\-|+]?\d+", RegexOptions.Compiled);

            if (rex.IsMatch(Value) == false) return DefaultValue;

            return rex.Match(Value).Value.GetInt();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static object Get(Type type, object Value)
        {
            if (Value.GetType() == type) return Value;
            if (type == typeof(string)) return Value.GetString();
            if (type == typeof(int)) return Value.GetInt();
            if (type == typeof(DateTime)) return Value.GetDateTime();
            if (type == typeof(decimal)) return Value.GetDecimal();
            if (type == typeof(Single)) return GetFloat(Value);
            if (type == typeof(float)) return GetFloat(Value);
            if (type == typeof(Int64)) return GetLong(Value);
            if (type == typeof(long)) return GetLong(Value);
            if (type == typeof(bool)) return Value.GetBool();

            TypeConverter t = TypeDescriptor.GetConverter(type);
            try
            {
                return t.ConvertFrom(Value);
            }
            catch
            {
                return Activator.CreateInstance(type);
            }
        }

        #region Contains


        public static bool Contains<T>(this IEnumerable<T> items, T value, Func<T, T, bool> equals)
        {
            return items.Contains(value, new FuncContainsComparer<T>(equals));
        }

        public class FuncContainsComparer<T> : IEqualityComparer<T>
        {
            private readonly Func<T, T, bool> _equals;
            public FuncContainsComparer(Func<T, T, bool> equals)
            {
                _equals = equals;
                //_hashCode = hashCode;
            }

            public bool Equals(T x, T y)
            {
                return _equals(x, y);
            }

            public int GetHashCode(T obj)
            {
                return obj.GetHashCode();
            }
        }
        #endregion
    }
}
